package edu.neusoft.yiqibike.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import edu.neusoft.yiqibike.common.datasource.TargetDataSource;
import edu.neusoft.yiqibike.common.entity.mongo.BikeLocation;
import edu.neusoft.yiqibike.common.entity.mysql.Admin;
import edu.neusoft.yiqibike.common.entity.mysql.Bike;
import edu.neusoft.yiqibike.common.entity.mysql.BreakdownRecord;
import edu.neusoft.yiqibike.common.entity.vo.BikeVo;
import edu.neusoft.yiqibike.common.exception.ArgumentVerifyException;
import edu.neusoft.yiqibike.common.util.MapperUtil;
import edu.neusoft.yiqibike.dao.IBikeLocationDao;
import edu.neusoft.yiqibike.service.IBikeService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 单车服务
 * User：lyc
 * Date：2018-01-26
 * Time：17:51
 * Description：
 */
@Service
public class BikeServiceImpl implements IBikeService {

    @Autowired
    private IBikeLocationDao bikeLocationDao;
    @Autowired
    private MongoOperations mongoTemplate;

    @Override
    @TargetDataSource(name = "ds2")
    public Page<BreakdownRecord> getBreakdownList(Page<BreakdownRecord> page) {
        return new BreakdownRecord().selectPage(page, new EntityWrapper<>());
    }

    /**
     * 受理用户的故障上报
     *
     * @param id     故障记录ID
     * @param status 更新后的状态
     * @param reason 驳回理由
     * @param admin  操作管理员
     */
    @Override
    @Transactional
    @TargetDataSource(name = "ds2")
    public void handleBreakdown(String id, Integer status, String reason, Admin admin) {
        BreakdownRecord breakdown = new BreakdownRecord();
        BreakdownRecord record = breakdown.selectById(id);
        if (Objects.nonNull(record) && record.getStatus() != 0) {
            throw new ArgumentVerifyException("该报修记录已审核");
        }
        breakdown.setId(id);
        breakdown.setStatus(status);
        if (StringUtils.isEmpty(reason) && status == 1) {
            reason = "审核通过";
        }
        breakdown.setResult(reason);
        breakdown.setHandleTime(new Date());
        if (Objects.nonNull(admin)) {
            breakdown.setHandler(admin.getId());
        }
        breakdown.updateById();
        this.breakdown(record.getBikeNo());
    }

    @Override
    @TargetDataSource(name = "ds2")
    public Page<BikeVo> getBikeList(Page<Bike> page) {
        Page<Bike> bikePage = new Bike().selectPage(page, new EntityWrapper<>());
        List<BikeVo> voList = new LinkedList<>();
        for (Bike bike : bikePage.getRecords()) {
            Optional<BikeLocation> bikeLocation = bikeLocationDao.findById(bike.getBikeNo());
            BikeVo vo = MapperUtil.getInstance().map(bike, BikeVo.class);
            if (bikeLocation.isPresent()) {
                vo.setLongitude(bikeLocation.get().getCoordinates()[0]);
                vo.setLatitude(bikeLocation.get().getCoordinates()[1]);
                if (!bike.getRecorder().equals("未知") && bike.getRecordTime() != null) {
                    vo.setIsRecord(1);
                }
            }
            voList.add(vo);
        }
        Page<BikeVo> voPage = new Page<>();
        voPage.setRecords(voList);
        voPage.setTotal(bikePage.getTotal());
        return voPage;
    }

    @Override
    @Transactional
    @TargetDataSource(name = "ds2")
    public boolean updateBike(Bike bike) {
        Integer status = bike.getStatus();
        int mongoStatus = -1;
        if (status == 4) {
            mongoStatus = 1;
        }
        Bike dbBike = bike.selectById();
        if (dbBike != null) {
            //修改单车状态同步至MONGODB
            mongoTemplate.updateFirst(new Query(new Criteria("_id").is(dbBike.getBikeNo())),
                    new Update().set("status", mongoStatus), BikeLocation.class);
            return bike.updateById();
        }
        return false;
    }

    @Override
    @Transactional
    @TargetDataSource(name = "ds2")
    public boolean addBike(Bike bike, Double[] location) {
        Integer status = -1;
        if (bike.getStatus() == 4) {
            status = 1;
        }
        bikeLocationDao.insert(new BikeLocation(bike.getBikeNo(), status, location));
        return bike.insert();
    }

    /**
     * 管理员紧急报修：
     * 1.更新单车状态
     * 2.通知抢修人员
     *
     * @param bikeNo 单车编号
     */
    @Override
    @Transactional
    @TargetDataSource(name = "ds2")
    public void breakdown(Long bikeNo) {
        Bike bike = new Bike().selectOne(new EntityWrapper().eq("bike_no", bikeNo));
        if (Objects.isNull(bike)) {
            throw new ArgumentVerifyException("当前单车没有记录在案");
        }
        //更新单车状态为待抢修
        bike.setStatus(2);
        this.updateBike(bike);
    }
}
